from glp.library import LabelUtils2
from glp.library import LabelInfo
from glp.library import DocumentMetadata
from collections import deque

class Reader:
    # v2 Interface

    special_labels = ('sort')
    sort_modes = ('alphabetical', 'popular', 'recent', 'rating')

    @staticmethod
    def GetCoLabels(labels, dst_type):
        return [(dst_type, label_id) for label_id in
                LabelUtils2.GetTypeLabels(dst_type)]

    @staticmethod
    def GetLabelParent(label):
        return LabelUtils2.GetLabelParent(label)

    @staticmethod
    def PrettifyLabel(label):
        return LabelUtils2.LabelToText(label)

    @staticmethod
    def ParseSearchQuery(q):
        # Move to unicode, switch to lowercase, and split on whitespace
        raw = unicode(q.lower()).split()
        terms = []
        for term in raw:
            bits = term.split(':', 1)
            if len(bits) == 1:
                terms.append(('word', term))
            elif bits[0] in Reader.special_labels:
                terms.append(('special', bits[0], bits[1]))
            else:
                terms.append(('label', bits[0], bits[1]))
        return terms

    @staticmethod
    def SegregateTerms(terms):
        segregated = { 'word': [], 'label': [], 'special': [] }
        for term in terms:
            segregated[term[0]].append(term)
        return segregated

    @staticmethod
    def SimpleSearchDocuments(term):
        if not term:
            term_id = '-'
        elif term[0] != 'label':
            return []
        else:
            term_id = ':'.join(term[1:])
        if term and term[1] == 'id':
            metadata = DocumentMetadata.get_by_key_name(term[2])
            if not metadata: return []
            return [metadata.key()]
        else:
            info = LabelInfo.get_by_key_name(term_id)
            if info == None: return []
            if info.documents == None: return []
            return info.documents

    @staticmethod
    def SearchDocuments(terms, limit):
        terms = Reader.SegregateTerms(terms)

        # Ignore words for now
        if len(terms['label']) == 0: terms['label'] = [None]
        keys = set(Reader.SimpleSearchDocuments(terms['label'][0]))
        for label in terms['label'][1:]:
            if not keys: return []
            keys &= set(Reader.SimpleSearchDocuments(label))

        metadata = DocumentMetadata.get(list(keys))

        sort_mode = 'alphabetical'
        for special in terms['special']:
            if special[1] == 'sort':
                sort_mode = special[2]
        if sort_mode == 'recent':
            metadata.sort(key=lambda item: item.id, reverse=True)
        else:
            metadata.sort(key=lambda item: item.title)

        if limit:
            metadata = metadata[0:limit]

        return metadata


    # v1 Interface

    @staticmethod
    def LabelTopics(label):
        if label == None: label = '-'
        info = LabelInfo.get_by_key_name(label)
        if info == None: return []
        topics = info.topics
        if topics == None: return []
        return topics

    @staticmethod
    def LabelsTopics(labels):
        if len(labels) == 0: return Reader.LabelTopics(None)
        topics = None
        for label in labels:
            if topics == None:
                topics = set(Reader.LabelTopics(label))
            else:
                topics &= set(Reader.LabelTopics(label))
        return list(topics)

    @staticmethod
    def LabelDocumentKeys(label):
        if label == None: label = '-'
        info = LabelInfo.get_by_key_name(label)
        if info == None: return []
        documents = info.documents
        if documents == None: return []
        return documents

    @staticmethod
    def LabelsDocumentKeys(labels):
        if len(labels) == 0: return Reader.LabelDocumentKeys(None)
        keys = None
        for label in labels:
            if keys == None:
                keys = set(Reader.LabelDocumentKeys(label))
            else:
                keys &= set(Reader.LabelDocumentKeys(label))
        return list(keys)

    @staticmethod
    def DocumentMetadata(id):
        return DocumentMetadata.get_by_key_name(id)
